【精选】Android 获取真实的进程运行时内存

您所在的位置:网站首页 android 查看运行内存 【精选】Android 获取真实的进程运行时内存

【精选】Android 获取真实的进程运行时内存

2023-10-19 10:35| 来源: 网络整理| 查看: 265

背景:

最近,在项目中做性能优化需要监控进程运行时内存。

笔者在​​​​​​Android 查看第三方应用进程的内存开销_xiaobaaidaba123的专栏-CSDN博客_android 内存开销

介绍过使用adb命令查看进程的内存开销。但是如果需要持续监控的话,需要另外的方法。

网上查找了下 使用ActivityManager 中的 getProcessMemoryInfo()方法可以获取到进程运行时内存,但是这个接口在 android P以上 限频了,拿到的内存可能是过去时间的,不能实时呈现运行时内存。而且不同的手机限频的时间不固定。

因此本文介绍的是另外一种方法:通过读取

"/proc/" + android.os.Process.myPid() + "/status" 路径文件里的信息获取。 1. 读文件获取运行时内存(RSS) public static long getProcessRealMemory() { String memFilePath = "/proc/" + android.os.Process.myPid() + "/status"; BufferedReader bufferedReader = null; try { FileInputStream fileInputStream = new FileInputStream(memFilePath); InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8"); bufferedReader = new BufferedReader(inputStreamReader); String line; while ((line = bufferedReader.readLine()) != null) { Log.d(TAG, " read line : " + line); if(!TextUtils.isEmpty(line) && line.contains("VmRSS")) { String rss = line.split(":")[1].trim().split( " ")[0]; return Integer.parseInt(rss) * 1024; } } } catch (Exception e) { e.printStackTrace(); } finally { if(bufferedReader != null) { try{ bufferedReader.close(); } catch (Exception e) { e.printStackTrace(); } } } return -1; }

优点:暂时没有权限限制,实时获取

缺点:这种读文件的方法拿到的内存是RSS。我们通常期望获取的是PSS

RSS和PSS 的区别:

RSS - Resident Set Size 实际使用物理内存(包含共享库占用的内存) PSS - Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)假如有3个进程使用同一个共享库,那么每个进程的PSS就包括了1/3大小的共享库内存。通常我们使用PSS大小来作为内存性能指标。  

2. 通过接口ActivityManager接口获取运行时内存(PSS)

ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); final Debug.MemoryInfo[] memInfo = activityManager.getProcessMemoryInfo(new int[]{android.os.Process.myPid()}); final int totalPss = memInfo[0].getTotalPss();

优点:获取的是PSS

缺点:安卓P以上限制频率,需要隔约5分钟(不同手机间隔不同)才能获取到新的值。而且获取的 PSS 不包括 Graphics。

3. 通过Runtime接口获取运行时内存(JVM消耗,不包括Native) long totalRuntimeMem = Runtime.getRuntime().totalMemory(); long freeRuntimeMem = Runtime.getRuntime().freeMemory(); long useRuntimeMem = totalRuntimeMem - freeRuntimeMem;

Runtime.getRuntime().totalMemory() 返回的是当前进程的java虚拟机从操作系统申请的总内存

Runtime.getRuntime().freeMemory() 返回的是当前进程的java虚拟机从操作系统申请的总内存中尚未使用的内存大小

那么运行时内存呢?笔者认为是totalMemory()-freeMemory()。代表当前进程的java虚拟机从操作系统申请的总内存中已经消耗的内存大小。

但是计算得到的值 是不包含native内存的,因为笔者发现Runtime计算得到的值 约等于PSS中的Java Heap的值,所以Runtime接口获取的运行时内存只是java层面的。(如有不对,欢迎各位看官一起指正,讨论)

4. 通过 Debug.getMemoryInfo(Debug.MemoryInfo memoryInfo) 接口。 Debug.MemoryInfo memoryInfo = new Debug.MemoryInfo(); Debug.getMemoryInfo(memoryInfo); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { String javaHeap = memoryInfo.getMemoryStat("summary.java-heap"); String nativeHeap = memoryInfo.getMemoryStat("summary.native-heap"); String code = memoryInfo.getMemoryStat("summary.code"); String stack = memoryInfo.getMemoryStat("summary.stack"); String graphics = memoryInfo.getMemoryStat("summary.graphics"); String privateOther = memoryInfo.getMemoryStat("summary.private-other"); String system = memoryInfo.getMemoryStat("summary.system"); String swap = memoryInfo.getMemoryStat("summary.total-swap"); }

优点:获取的是PSS,并且没有限频,可以获取到 PSS 的组成部分

缺点:获取的 PSS 不包括 Graphics。Android 6 以下不能通过 Debug.MemoryInfo.getmemoryStat 接口获取组成部分的占用内存,只能通过反射方法获取。

总结:

我们应该用哪种方法来对运行时内存进行监控呢? 

业界的 APM 工具基本用的是方法2 或者方法4,尽管缺少 Graphics,但是能监控应用大体的运行时内存变化。后续笔者也会调研如何获取 Graphics 部分的内存。欢迎各位看官一起交流~

Demo效果:

 GitHub - mikelhm/MikelProjectDemo: Personal Android Demo



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3